package com.sdk.paas.core.base;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.sdk.paas.PaasResult;
import com.sdk.paas.core.AccessConfig;
import com.sdk.paas.core.HttpLogEntity;
import com.sdk.paas.core.config.ProConfig;
import com.sdk.paas.core.config.TestConfig;
import com.sdk.paas.core.enums.EnvEnum;
import com.sdk.paas.core.enums.ErrorEnum;
import com.sdk.paas.core.enums.PlatformTypeEnum;
import com.sdk.paas.core.exception.SaasToolDetailException;
import com.sdk.paas.core.exception.SaasToolException;
import com.sdk.paas.core.utils.LogUtil;
import com.sdk.paas.core.utils.SignUtil;
import com.sdk.paas.req.PaasUploadFaceReq;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public abstract class BaseService {

    private static Logger reqLog = LoggerFactory.getLogger("httpRequestLog");

    /**
     * paas-post请求
     *
     * @param url
     * @param data
     * @param typeOfT
     * @param config
     * @param <T>
     * @param <Z>
     * @return
     */
    protected <T, Z> Z postPaas(String url, T data, Type typeOfT, AccessConfig config) {
        Long startTime = System.currentTimeMillis();
        String res = "";
        try {
            paasConfig(config);
            url = config.getHost()+url;
            String body = JSONObject.toJSONString(data, SerializerFeature.SortField);
            final Map<String, String> headerMap = this.paasPostRequestHeaderMap(body, config);
            res = post(url, body, headerMap, PlatformTypeEnum.PAAS.getType(), startTime);
            return new Gson().fromJson(res, typeOfT);
        } catch (SaasToolException e) {
            res = PaasResult.fail(e.getCode(), e.getMessage());
        } catch (SaasToolDetailException e) {
            res = PaasResult.fail(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error("JSON字符串转对象异常:{},{},{},{}", url, PlatformTypeEnum.PAAS.getType(), res, e);
            res = PaasResult.fail(ErrorEnum.JSON_ERROR);
        }
        return new Gson().fromJson(res, typeOfT);
    }

    /**
     * paas请求头部参数
     *
     * @param body
     * @param config
     * @return
     */
    private Map<String, String> paasPostRequestHeaderMap(String body, AccessConfig config) {
        Map<String, String> headers = new HashMap<>();
        String xCaTime = Long.toString(System.currentTimeMillis() / 1000L);
        headers.put("reqId", IdUtil.fastSimpleUUID());
        headers.put("x-ca-appKey", config.getAppKey());
        headers.put("x-ca-timestamp", xCaTime);
        StringBuilder stringBuilder = new StringBuilder(config.getAppKey());
        stringBuilder.append(xCaTime);
        stringBuilder.append(body);
        try {
            headers.put("x-ca-sign", SignUtil.sign(stringBuilder.toString(), config.getAppSecret()));
        } catch (Exception e) {
            log.error("签名异常:{},{},{}", PlatformTypeEnum.PAAS.getType(), body, e);
            throw new SaasToolException(ErrorEnum.SIGN_ERROR);
        }
        return headers;
    }

    /**
     * @param url
     * @param body
     * @param headers
     * @param type
     * @param startTime
     * @author limaosheng
     * @create 18:09 2022/8/8
     */
    private String post(String url, String body, Map<String, String> headers, String type, Long startTime) {
        HttpLogEntity httpLogEntity = new HttpLogEntity(type, url, body, headers, startTime);
        String res;
        int httpCode;
        try {
            if (headers == null) {
                headers = new HashMap<>();
            }
            HttpResponse httpResponse = HttpRequest.post(url).headerMap(headers, true).timeout(10000)
                    .contentType("application/json").body(body).execute();
            res = httpResponse.body();
            httpCode = httpResponse.getStatus();
        } catch (Exception e) {
            //请求超时等异常，统一为请求异常往外层抛
            reqLog.info(LogUtil.logExc(httpLogEntity, e));
            throw new SaasToolException(ErrorEnum.REQUEST_ERROR);
        }
        httpLogEntity.setCode(httpCode);
        httpLogEntity.setResponseBody(res);
        if (HttpStatus.HTTP_OK != httpCode) {
            reqLog.info(LogUtil.httpCodeErr(httpLogEntity));
            throw new SaasToolDetailException(ErrorEnum.REQUEST_FAIL_ERROR, String.valueOf(httpCode));
        }
        reqLog.info(LogUtil.comm(httpLogEntity));
        return res;
    }

    /**
     * paas平台人脸图片上传
     *
     * @param url
     * @param req
     * @param config
     * @author limaosheng
     * @create 14:54 2022/8/10
     */
    public PaasResult<String> paasUploadFacePost(String url, PaasUploadFaceReq req, AccessConfig config) {
        Long startTime = System.currentTimeMillis();
        paasConfig(config);
        url = config.getHost() + url;
        HttpLogEntity httpLogEntity = new HttpLogEntity(PlatformTypeEnum.PAAS.getType(), url, req.getCode() + req.getOrgCode(), null, startTime);
        String res;
        int httpCode;
        try {
            HttpResponse httpResponse = HttpRequest.post(url).timeout(60000)
                    .contentType(ContentType.MULTIPART.getValue())
                    .form("imagesData", req.getImagesData())
                    .form("code", req.getCode())
                    .form("orgCode", req.getOrgCode())
                    .form("operator", req.getOperator())
                    .execute();
            res = httpResponse.body();
            httpCode = httpResponse.getStatus();
        } catch (Exception e) {
            //请求超时等异常，统一为请求异常往外层抛
            reqLog.info(LogUtil.logExc(httpLogEntity, e));
            throw new SaasToolException(ErrorEnum.REQUEST_ERROR);
        }
        httpLogEntity.setCode(httpCode);
        httpLogEntity.setResponseBody(res);
        if (HttpStatus.HTTP_OK != httpCode) {
            reqLog.info(LogUtil.httpCodeErr(httpLogEntity));
            throw new SaasToolDetailException(ErrorEnum.REQUEST_FAIL_ERROR, String.valueOf(httpCode));
        }
        reqLog.info(LogUtil.comm(httpLogEntity));
        try {
            return new Gson().fromJson(res, new TypeToken<PaasResult<String>>() {
            }.getType());
        } catch (JsonSyntaxException e) {
            log.info("JSON字符串转对象异常:{},{},{},{}", url, PlatformTypeEnum.PAAS.getType(), res, e);
            throw new SaasToolException(ErrorEnum.JSON_ERROR);
        }
    }

    /**
     * PAAS
     *
     * @param config
     * @author limaosheng
     * @create 9:18 2022/8/23
     */
    private void paasConfig(AccessConfig config) {
        if (StrUtil.isBlank(config.getEnv())) {
            return;
        }
        if (EnvEnum.PRO.getEnv().equals(config.getEnv())) {
            config.setHost(ProConfig.PAAS_HOST);
            config.setAppKey(ProConfig.PAAS_APP_KEY);
            config.setAppSecret(ProConfig.PAAS_APP_SECRET);
        } else {
            config.setHost(TestConfig.PAAS_HOST);
            config.setAppKey(TestConfig.PAAS_APP_KEY);
            config.setAppSecret(TestConfig.PAAS_APP_SECRET);
        }
    }
}
